Vladimir Nadvornik contributes a the sdistance option to split tracks by distance.
authorrobertl <robertl>
Wed, 25 Oct 2006 10:51:13 +0000 (10:51 +0000)
committerrobertl <robertl>
Wed, 25 Oct 2006 10:51:13 +0000 (10:51 +0000)
trackfilter.c
xmldoc/filters/options/track-sdistance.xml [new file with mode: 0644]

index a5edc2870f689f07e3769cfa1a063616bb85ec56..7b5cf60a6aa48f4efb683fec29a1263cc6e814f0 100644 (file)
@@ -43,6 +43,7 @@
 
 #define TRACKFILTER_PACK_OPTION                "pack"
 #define TRACKFILTER_SPLIT_OPTION       "split"
+#define TRACKFILTER_SDIST_OPTION       "sdistance"
 #define TRACKFILTER_TITLE_OPTION       "title"
 #define TRACKFILTER_MERGE_OPTION       "merge"
 #define TRACKFILTER_NAME_OPTION                "name"
@@ -58,6 +59,7 @@
 static char *opt_merge = NULL;
 static char *opt_pack = NULL;
 static char *opt_split = NULL;
+static char *opt_sdistance = NULL;
 static char *opt_move = NULL;
 static char *opt_title = NULL;
 static char *opt_start = NULL;
@@ -77,6 +79,9 @@ arglist_t trackfilter_args[] = {
        {TRACKFILTER_SPLIT_OPTION, &opt_split, 
            "Split by date or time interval (see README)", NULL, 
            ARGTYPE_STRING, ARG_NOMINMAX},
+       {TRACKFILTER_SDIST_OPTION, &opt_sdistance, 
+           "Split by distance", NULL, 
+           ARGTYPE_STRING, ARG_NOMINMAX},
        {TRACKFILTER_MERGE_OPTION, &opt_merge, 
            "Merge multiple tracks for the same way", NULL, ARGTYPE_STRING, 
            ARG_NOMINMAX},
@@ -113,6 +118,7 @@ static trkflt_t *track_list = NULL;
 static int track_ct = 0;
 static int track_pts = 0;
 static int opt_interval = 0;
+static int opt_distance = 0;
 
 /*******************************************************************************
 * helpers
@@ -466,17 +472,19 @@ trackfilter_split(void)
        queue *elem, *tmp;
        int i, j;
        float interval = -1;
+       float distance = -1; 
 
        if (count <= 1) return;
 
        /* check additional options */
        
-       opt_interval = ((strlen(opt_split) > 0) && (0 != strcmp(opt_split, TRACKFILTER_SPLIT_OPTION)));
+       opt_interval = (opt_split && (strlen(opt_split) > 0) && (0 != strcmp(opt_split, TRACKFILTER_SPLIT_OPTION)));
+       opt_distance = (opt_sdistance && (strlen(opt_sdistance) > 0) && (0 != strcmp(opt_sdistance, TRACKFILTER_SDIST_OPTION)));
 
        if (opt_interval != 0)
        {
            float  base;
-           char   dhms;
+           char   unit;
            
            switch(strlen(opt_split))
            {
@@ -485,16 +493,16 @@ trackfilter_split(void)
                    break; /* ? */
                    
                case 1:
-                   dhms = *opt_split;
+                   unit = *opt_split;
                    interval = 1;
                    break;
                    
                default:
-                   i = sscanf(opt_split,"%f%c", &interval, &dhms);
+                   i = sscanf(opt_split,"%f%c", &interval, &unit);
                    if (i == 0) 
                    {
                        /* test reverse order */
-                       i = sscanf(opt_split,"%c%f", &dhms, &interval);
+                       i = sscanf(opt_split,"%c%f", &unit, &interval);
                    }
                    if ((i != 2) || (interval <= 0))
                    {
@@ -503,7 +511,7 @@ trackfilter_split(void)
                    break;
            }
 
-           switch(tolower(dhms))
+           switch(tolower(unit))
            {
                case 's':
                    base = 1;
@@ -522,11 +530,59 @@ trackfilter_split(void)
                    break;
            }
 #ifdef TRACKF_DBG
-           printf(MYNAME ": dhms \"%c\", interval %g -> %g\n", dhms, interval, base * interval);
+           printf(MYNAME ": unit \"%c\", interval %g -> %g\n", unit, interval, base * interval);
 #endif
            interval *= base;
        }
 
+       if (opt_distance != 0)
+       {
+           float  base;
+           char   unit;
+           
+           switch(strlen(opt_sdistance))
+           {
+               case 0:
+                   fatal(MYNAME ": No distance specified.\n");
+                   break; /* ? */
+                   
+               case 1:
+                   unit = *opt_sdistance;
+                   distance = 1;
+                   break;
+                   
+               default:
+                   i = sscanf(opt_sdistance,"%f%c", &distance, &unit);
+                   if (i == 0) 
+                   {
+                       /* test reverse order */
+                       i = sscanf(opt_sdistance,"%c%f", &unit, &distance);
+                   }
+                   if ((i != 2) || (distance <= 0))
+                   {
+                       fatal(MYNAME ": invalid distance specified, must be one a positive number.\n");
+                   }
+                   break;
+           }
+
+           switch(tolower(unit))
+           {
+               case 'k': /* kilometers */
+                   base = 0.6214;
+                   break;
+               case 'm': /* miles */
+                   base = 1;
+                   break;
+               default:
+                   fatal(MYNAME ": invalid distance specified, must be one of [km].\n");
+                   break;
+           }
+#ifdef TRACKF_DBG
+           printf(MYNAME ": unit \"%c\", distance %g -> %g\n", unit, distance, base * distance);
+#endif
+           distance *= base;
+       }
+
        trackfilter_split_init_rte_name(master, track_list[0].first_time);
        
        buff = (waypoint **) xcalloc(count, sizeof(*buff));
@@ -544,7 +600,7 @@ trackfilter_split(void)
        {
            int new_track_flag;
            
-           if (opt_interval == 0)
+           if ((opt_interval == 0) && (opt_distance == 0))
            {
                struct tm t1, t2;
                
@@ -560,17 +616,41 @@ trackfilter_split(void)
            }
            else
            {
-               float tr_interval;
+               new_track_flag = 1;
                
-               tr_interval = difftime(buff[j]->creation_time,buff[i]->creation_time);
-               new_track_flag = ( tr_interval > interval );
+               if (distance > 0) 
+               {
+                   double rt1 = RAD(buff[i]->latitude);
+                   double rn1 = RAD(buff[i]->longitude);
+                   double rt2 = RAD(buff[j]->latitude);
+                   double rn2 = RAD(buff[j]->longitude);
+                   double curdist = gcdist( rt1, rn1, rt2, rn2 );
+                   curdist = radtomiles(curdist);
+                   if ( curdist <= distance ) 
+                       new_track_flag = 0;
 #ifdef TRACKF_DBG
-               if (new_track_flag != 0)
-                   printf(MYNAME ": split, %g > %g\n", tr_interval, interval );
+                   else
+                       printf(MYNAME ": sdistance, %g > %g\n", curdist, distance );
+#endif
+               }
+               
+               if (interval > 0)
+               {
+                   float tr_interval = difftime(buff[j]->creation_time,buff[i]->creation_time);
+                   if ( tr_interval <= interval ) 
+                       new_track_flag = 0;
+#ifdef TRACKF_DBG
+                   else
+                       printf(MYNAME ": split, %g > %g\n", tr_interval, interval );
 #endif
+               }
+
            }
            if (new_track_flag != 0)
            {
+#ifdef TRACKF_DBG
+               printf(MYNAME ": splitting new track\n" );
+#endif
                curr = (route_head *) route_head_alloc();
                trackfilter_split_init_rte_name(curr, buff[j]->creation_time);
                track_add_head(curr);
@@ -871,7 +951,7 @@ trackfilter_process(void)
            return;
        }
        
-       if (opt_split != NULL)
+       if ((opt_split != NULL) || (opt_sdistance != NULL))
        {
            if (track_ct > 1) 
                fatal(MYNAME "-split: Cannot split more than one track, please pack (or merge) before!\n");
diff --git a/xmldoc/filters/options/track-sdistance.xml b/xmldoc/filters/options/track-sdistance.xml
new file mode 100644 (file)
index 0000000..7fc4db8
--- /dev/null
@@ -0,0 +1,36 @@
+         <para> The input track will be split into several tracks
+         if the distance between successive track points
+         is greater than the distance given as a parameter.
+         The distance must be numeric and can be in miles or kilometers,
+         expressed as one of the character "k", or "m".
+       If sdistance is given no parameters, this option has the same 
+       effect as the split option without parameters. If there is more 
+       than one track,
+         use the pack option before before using this.</para>
+
+         <para> For example, to split the track if the distance between
+         points is greater than 100 meters, use this:</para>
+         <screen format="linespecific">
+gpsbabel -t \
+     -i gpx -f in.gpx \
+     -x track,pack,sdistance=0.1k" \
+     -o gpx -F out.gpx
+</screen>
+        <para> The sdistance option can be combined with the split option.
+        The track then will be split only if both time and distance
+        interval exceeds the supplied values. This technique can be used to 
+       filter out gaps from
+        the tracklog.  The gap is kept only if the gps device is without
+        signal for longer time than that given and during that time it moves 
+       a distance over that given.
+        This example splits the track
+        if the device is without signal for at least 5 minutes
+        and during this time moves more than 300 meters:</para>
+        <screen format="linespecific">
+gpsbabel -t \
+     -i gpx -f in.gpx \
+     -x track,pack,sdistance=0.3k,split=5m \
+     -o gpx -F out.gpx
+</screen>
+
+